#lang racket

(require (prefix-in rx/
					(combine-in
					 "definition.rkt"
					 "observable.rkt"
					 "subject.rkt"
					 "subscriber.rkt"
					 "disposable.rkt"))
		 "operation.rkt")

(provide (all-from-out
		  "definition.rkt"
		  "observable.rkt"
		  "subject.rkt"
		  "subscriber.rkt"
		  "disposable.rkt"
		  "operation.rkt")
		 rx+ rx*)

(begin-for-syntax
 (define (transform-rxexp exp sender prefix)
   (if (identifier? exp)
	   exp
	   (let* ([lst (syntax->list exp)]
			  [fun1 (car lst)]
			  [fun2
			   (if prefix
				   #`#,(string->symbol (format "~a~a" prefix (syntax-e fun1)))
				   (car lst))]
			  [args (if sender (cons sender (cdr lst)) (cdr lst))])
		 (if (identifier-binding fun2)
			 (cons fun2 args)
			 (cons fun1 args))))))

(define-syntax (rx* stx)
  (syntax-case stx ()
	[(_ o proc ...)
	 (with-syntax ([o2 (transform-rxexp #'o #f 'rx/)]
				   [(do-proc ...)
					(map (lambda (exp)
						   (transform-rxexp exp #'obj 'rx/))
						 (syntax->list #'(proc ...)))])
	   #'(let ([obj o2])
		   do-proc ...))]))

(define-syntax (rx+ stx)
  (syntax-case stx ()
	[(_ o proc ...)
	 (with-syntax ([o2 (transform-rxexp #'o #f 'rx/)]
				   [do-proc
					(foldl (lambda (a b)
							 (transform-rxexp a b 'rx/))
						   #'obj (syntax->list #'(proc ...)))])
	   #'(let ([obj o2])
		   do-proc))]))


